package com.vegetable.modules.service.finance.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.modules.entity.baseData.AddressBook;
import com.vegetable.modules.entity.finance.PaymentPurchase;
import com.vegetable.modules.entity.finance.TransactionPaymentMatch;
import com.vegetable.modules.entity.finance.Transactions;
import com.vegetable.modules.entity.finance.vo.TransactionPaymentMatchVO;
import com.vegetable.modules.exception.TransactionPaymentMatchException;
import com.vegetable.modules.mapper.baseData.AddressBookMapper;
import com.vegetable.modules.mapper.finance.PaymentPurchaseMapper;
import com.vegetable.modules.mapper.finance.TransactionPaymentMatchMapper;
import com.vegetable.modules.mapper.finance.TransactionsMapper;
import com.vegetable.modules.service.finance.ITransactionPaymentMatchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 交易流水与付款记录匹配关系 服务实现类
 * </p>
 *
 * @author Qoder
 * @since 2025-11-02
 */
@Slf4j
@Service
public class TransactionPaymentMatchServiceImpl extends ServiceImpl<TransactionPaymentMatchMapper, TransactionPaymentMatch> implements ITransactionPaymentMatchService {

    @Autowired
    private TransactionPaymentMatchMapper transactionPaymentMatchMapper;

    @Autowired
    private TransactionsMapper transactionsMapper;

    @Autowired
    private PaymentPurchaseMapper paymentPurchaseMapper;

    @Autowired
    private AddressBookMapper addressBookMapper;

    @Override
    public List<TransactionPaymentMatchVO> listByPaymentId(Long paymentId) {
        return transactionPaymentMatchMapper.selectByPaymentId(paymentId);
    }

    @Override
    public List<TransactionPaymentMatch> listByTransactionId(Long transactionId) {
        return transactionPaymentMatchMapper.selectByTransactionId(transactionId);
    }
    
    @Override
    public List<TransactionPaymentMatch> listByPaymentIdWithTransactionInfo(Long paymentId) {
        return transactionPaymentMatchMapper.selectByPaymentIdWithTransactionInfo(paymentId);
    }

    @Override
    public List<TransactionPaymentMatch> listByTransactionIdWithPaymentInfo(Long transactionId) {
        return transactionPaymentMatchMapper.selectByTransactionIdWithPaymentInfo(transactionId);
    }

    @Override
    public List<TransactionPaymentMatchVO> listVOByPaymentId(Long paymentId) {
        List<TransactionPaymentMatchVO> matches = listByPaymentId(paymentId);
        List<TransactionPaymentMatchVO> vos = new ArrayList<>();

        for (TransactionPaymentMatchVO match : matches) {
//            TransactionPaymentMatchVO vo = new TransactionPaymentMatchVO();
//            BeanUtils.copyProperties(match, vo);

//            // 获取交易流水信息
//            Transactions transaction = transactionsMapper.selectById(match.getTransactionId());
//            if (transaction != null) {
//                TransactionPaymentMatchVO.TransactionsVO transactionVO = new TransactionPaymentMatchVO.TransactionsVO();
//                BeanUtils.copyProperties(transaction, transactionVO);
//                match.setTransactionInfo(transactionVO);
//            }

            // 获取付款记录信息
            PaymentPurchase payment = paymentPurchaseMapper.selectById(match.getPaymentId());
            if (payment != null) {
                TransactionPaymentMatchVO.PaymentPurchaseVO paymentVO = new TransactionPaymentMatchVO.PaymentPurchaseVO();
                BeanUtils.copyProperties(payment, paymentVO);
                match.setPaymentInfo(paymentVO);
            }

            vos.add(match);
        }

        return vos;
    }

    @Override
    public List<TransactionPaymentMatchVO> listVOByTransactionId(Long transactionId) {
        List<TransactionPaymentMatch> matches = listByTransactionId(transactionId);
        List<TransactionPaymentMatchVO> vos = new ArrayList<>();

        for (TransactionPaymentMatch match : matches) {
            TransactionPaymentMatchVO vo = new TransactionPaymentMatchVO();
            BeanUtils.copyProperties(match, vo);

//            // 获取交易流水信息
//            Transactions transaction = transactionsMapper.selectById(match.getTransactionId());
//            if (transaction != null) {
//                TransactionPaymentMatchVO.TransactionsVO transactionVO = new TransactionPaymentMatchVO.TransactionsVO();
//                BeanUtils.copyProperties(transaction, transactionVO);
//                vo.setTransactionInfo(transactionVO);
//            }

            // 获取付款记录信息
            PaymentPurchase payment = paymentPurchaseMapper.selectById(match.getPaymentId());
            if (payment != null) {
                TransactionPaymentMatchVO.PaymentPurchaseVO paymentVO = new TransactionPaymentMatchVO.PaymentPurchaseVO();
                BeanUtils.copyProperties(payment, paymentVO);
                vo.setPaymentInfo(paymentVO);
            }

            vos.add(vo);
        }

        return vos;
    }

    /**
     * 查询某个付款记录已匹配的金额
     * @param paymentId 付款记录ID
     * @return
     */
    @Override
    public BigDecimal getMatchedAmountByPaymentId(Long paymentId) {
        return transactionPaymentMatchMapper.selectMatchedAmountByPaymentId(paymentId);
    }
    
    @Override
    public BigDecimal getMatchedAmountByTransactionId(Long transactionId) {
        return transactionPaymentMatchMapper.selectMatchedAmountByTransactionId(transactionId);
    }

    @Override
    public boolean removeByPaymentIdAndTransactionId(Long paymentId, Long transactionId) {
        // 获取要删除的匹配记录，用于后续更新交易流水的matchedAmount
        QueryWrapper<TransactionPaymentMatch> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("payment_id", paymentId);
        queryWrapper.eq("transaction_id", transactionId);
        TransactionPaymentMatch matchToRemove = transactionPaymentMatchMapper.selectOne(queryWrapper);
        
        int result = transactionPaymentMatchMapper.deleteByPaymentIdAndTransactionId(paymentId, transactionId);
        
        // 如果删除成功且存在匹配记录，则更新交易流水的matchedAmount
        if (result > 0 && matchToRemove != null) {
            Transactions transaction = transactionsMapper.selectById(transactionId);
            if (transaction != null) {
                // 通过查询汇总的方式更新matchedAmount，确保数据准确性
                BigDecimal matchedAmount = getMatchedAmountByTransactionId(transactionId);
                transaction.setMatchedAmount(matchedAmount);
                transactionsMapper.updateById(transaction);
                log.info("更新交易流水ID {} 的已匹配金额为: {}", transaction.getId(), transaction.getMatchedAmount());
            }
        }
        
        // 检查并更新付款记录状态
        checkAndUpdatePaymentState(paymentId);
        return result > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reallocateTransactionToPayment(Long transactionId, Long targetPaymentId, BigDecimal allocateAmount) {
        log.info("开始重新分配交易流水到目标付款记录, 交易流水ID: {}, 目标付款记录ID: {}, 分配金额: {}", 
                transactionId, targetPaymentId, allocateAmount);
        
        // 获取交易流水信息
        Transactions transaction = transactionsMapper.selectById(transactionId);
        if (transaction == null) {
            log.error("交易流水ID {} 不存在", transactionId);
            throw new TransactionPaymentMatchException("交易流水不存在");
        }
        
        // 获取目标付款记录信息
        PaymentPurchase targetPayment = paymentPurchaseMapper.selectById(targetPaymentId);
        if (targetPayment == null) {
            log.error("目标付款记录ID {} 不存在", targetPaymentId);
            throw new TransactionPaymentMatchException("目标付款记录不存在");
        }
        
        // 检查交易流水与目标付款记录的当前匹配状态
        QueryWrapper<TransactionPaymentMatch> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("transaction_id", transactionId);
        queryWrapper.eq("payment_id", targetPaymentId);
        TransactionPaymentMatch existingMatch = transactionPaymentMatchMapper.selectOne(queryWrapper);
        
        // 判断是新增分配还是调整分配
        boolean isAdjustment = existingMatch != null;
        
        // 如果是调整分配，先删除原有的关联关系
        if (isAdjustment) {
            log.info("检测到调整分配操作，先删除原有匹配关系");
            transactionPaymentMatchMapper.delete(queryWrapper);
            // 检查并更新原付款记录状态
            checkAndUpdatePaymentState(targetPaymentId);
        }
        
        // 计算交易流水剩余可匹配金额
        BigDecimal transactionAmount = transaction.getTradingAmount() != null ? transaction.getTradingAmount() : BigDecimal.ZERO;
        BigDecimal currentMatchedAmount = getMatchedAmountByTransactionId(transactionId);
        
        // 如果是调整分配，需要将原分配金额加回到剩余可匹配金额中
        BigDecimal remainingAmount = transactionAmount.subtract(currentMatchedAmount);
        if (isAdjustment) {
            remainingAmount = remainingAmount.add(existingMatch.getMatchAmount());
        }
        
        log.info("交易流水ID {}: 交易金额={}, 当前已匹配金额={}, 剩余可匹配金额={}", 
                transactionId, transactionAmount, currentMatchedAmount, remainingAmount);
        
        // 确保剩余可匹配金额大于0
        if (remainingAmount.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("交易流水ID {} 已经完全匹配，剩余可匹配金额为0", transaction.getId());
            throw new TransactionPaymentMatchException("交易流水已经完全匹配，无剩余可匹配金额");
        }
        
        // 计算目标付款记录的剩余可匹配金额
        BigDecimal targetPaymentMatchedAmount = getMatchedAmountByPaymentId(targetPaymentId);
        BigDecimal targetPaymentAmount = targetPayment.getMoney() != null ? targetPayment.getMoney() : BigDecimal.ZERO;
        
        // 如果是调整分配，需要将原分配金额从已匹配金额中减去
        BigDecimal adjustedTargetMatchedAmount = targetPaymentMatchedAmount;
        if (isAdjustment) {
            adjustedTargetMatchedAmount = targetPaymentMatchedAmount.subtract(existingMatch.getMatchAmount());
        }
        
        BigDecimal targetPaymentRemainingAmount = targetPaymentAmount.subtract(adjustedTargetMatchedAmount);
        
        log.info("目标付款记录ID {}: 付款金额={}, 当前已匹配金额={}, 调整后已匹配金额={}, 剩余可匹配金额={}", 
                targetPaymentId, targetPaymentAmount, targetPaymentMatchedAmount, adjustedTargetMatchedAmount, targetPaymentRemainingAmount);
        
        // 确保目标付款记录还有剩余可匹配金额
        if (targetPaymentRemainingAmount.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("目标付款记录ID {} 已经完全匹配，剩余可匹配金额为0", targetPaymentId);
            throw new TransactionPaymentMatchException("目标付款记录已经完全匹配，无剩余可匹配金额");
        }
        
        // 确定实际分配金额
        BigDecimal actualAllocateAmount;
        if (allocateAmount != null) {
            // 使用指定的分配金额
            actualAllocateAmount = allocateAmount;
        } else {
            // 自动计算分配金额（取交易流水剩余金额和付款记录剩余金额的较小值）
            actualAllocateAmount = remainingAmount.min(targetPaymentRemainingAmount);
        }
        
        // 检查分配金额是否超过限制，如果是则抛出业务异常
        if (actualAllocateAmount.compareTo(remainingAmount) > 0) {
            log.error("指定分配金额 {} 超过交易流水剩余可匹配金额 {}", actualAllocateAmount, remainingAmount);
            throw new TransactionPaymentMatchException(
                String.format("指定分配金额 %.2f 超过交易流水剩余可匹配金额 %.2f", 
                    actualAllocateAmount.doubleValue(), remainingAmount.doubleValue()));
        }
        
        if (actualAllocateAmount.compareTo(targetPaymentRemainingAmount) > 0) {
            log.error("指定分配金额 {} 超过目标付款记录剩余可匹配金额 {}", actualAllocateAmount, targetPaymentRemainingAmount);
            throw new TransactionPaymentMatchException(
                String.format("指定分配金额 %.2f 超过目标付款记录剩余可匹配金额 %.2f", 
                    actualAllocateAmount.doubleValue(), targetPaymentRemainingAmount.doubleValue()));
        }
        
        // 确保分配金额大于0
        if (actualAllocateAmount.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("分配金额必须大于0");
            throw new TransactionPaymentMatchException("分配金额必须大于0");
        }
        
        log.info("确定实际分配金额: {}", actualAllocateAmount);
        
        // 创建新的关联关系
        TransactionPaymentMatch match = new TransactionPaymentMatch();
        match.setTransactionId(transactionId);
        match.setPaymentId(targetPaymentId);
        match.setMatchAmount(actualAllocateAmount);
        match.setMatchTime(new Date());
        match.setCreateTime(new Date());
        match.setUpdateTime(new Date());
        int result = transactionPaymentMatchMapper.insert(match);
        
        if (result > 0) {
            log.info("成功创建匹配关系，匹配ID: {}", match.getId());
        } else {
            log.error("创建匹配关系失败，交易流水ID: {}, 付款记录ID: {}", transactionId, targetPaymentId);
            throw new TransactionPaymentMatchException("创建匹配关系失败");
        }
        
        // 更新交易流水的已匹配金额，通过查询汇总的方式确保数据准确性
        BigDecimal updatedMatchedAmount = getMatchedAmountByTransactionId(transactionId);
        transaction.setMatchedAmount(updatedMatchedAmount);
        transactionsMapper.updateById(transaction);
        log.debug("更新交易流水ID {} 的已匹配金额为: {}", transaction.getId(), transaction.getMatchedAmount());
        
        // 检查并更新目标付款记录状态
        checkAndUpdatePaymentState(targetPaymentId);
        
        log.info("完成交易流水重新分配到目标付款记录, 交易流水ID: {}", transactionId);
        return result > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean autoMatchTransactionToPayment(Transactions transaction) {
        log.info("开始自动匹配交易流水与代办付款记录, 交易流水ID: {}", transaction.getId());
        
        // 检查交易流水是否有 ab_id
        if (transaction.getAbId() == null) {
            log.info("交易流水ID {} 的 ab_id 为空，无法进行自动匹配", transaction.getId());
            return false;
        }
        log.debug("交易流水ID {} 的 ab_id 为: {}", transaction.getId(), transaction.getAbId());

        // 获取对应的通讯录记录
        AddressBook addressBook = addressBookMapper.selectById(transaction.getAbId());
        if (addressBook == null) {
            log.info("未找到交易流水ID {} 对应的通讯录记录 (ab_id: {})", transaction.getId(), transaction.getAbId());
            return false;
        }
        
        if (addressBook.getStaffType() != 2) { // 2表示代办
            log.info("交易流水ID {} 对应的通讯录记录 (ab_id: {}) 不是代办类型, staffType: {}", 
                     transaction.getId(), transaction.getAbId(), addressBook.getStaffType());
            return false;
        }
        log.info("找到代办类型的通讯录记录, ab_id: {}, 名称: {}", addressBook.getId(), addressBook.getNoteName());

        // 查找对应的代办付款记录（order_type=1表示代办付款）
        // 使用条件查询代替全表扫描，按交易时间从早到晚排序，找到第一个未完全匹配的代办付款记录
        QueryWrapper<PaymentPurchase> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_type", 1);
        queryWrapper.eq("customer_id", transaction.getAbId());
        queryWrapper.orderByDesc("order_time").orderByAsc("id");
        List<PaymentPurchase> paymentList = paymentPurchaseMapper.selectList(queryWrapper);
        log.info("找到 {} 条代办付款记录用于匹配", paymentList.size());
        
        PaymentPurchase targetPayment = null;
        BigDecimal thisMatched = BigDecimal.ZERO;
        for (PaymentPurchase payment : paymentList) {
            // 检查该付款记录是否已完全匹配
            BigDecimal matchedAmount = getMatchedAmountByPaymentId(payment.getId());
            BigDecimal paymentAmount = payment.getMoney() != null ? payment.getMoney() : BigDecimal.ZERO;
            log.info("付款记录ID {}: 应付金额={}, 已匹配金额={}", payment.getId(), paymentAmount, matchedAmount);
            
            if (NumberUtil.isLess(matchedAmount, paymentAmount)) {
                targetPayment = payment;
                log.info("选择付款记录ID {} 作为匹配目标", targetPayment.getId());
                break;
            }
        }

        // 如果没有找到合适的付款记录，返回false
        if (targetPayment == null) {
            log.info("未找到适合匹配的代办付款记录，交易流水ID: {}", transaction.getId());
            return false;
        }

        // 计算交易流水剩余可匹配金额
        BigDecimal transactionAmount = transaction.getTradingAmount() != null ? transaction.getTradingAmount() : BigDecimal.ZERO;
        BigDecimal matchedAmount = transaction.getMatchedAmount() != null ? transaction.getMatchedAmount() : BigDecimal.ZERO;
        BigDecimal remainingAmount = transactionAmount.subtract(matchedAmount);
        
        // 确保剩余可匹配金额大于0
        if (remainingAmount.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("交易流水ID {} 已经完全匹配，剩余可匹配金额为0", transaction.getId());
            return false;
        }
        
        // 检查目标付款记录的剩余可匹配金额
        BigDecimal paymentMatchedAmount = getMatchedAmountByPaymentId(targetPayment.getId());
        BigDecimal paymentAmount = targetPayment.getMoney() != null ? targetPayment.getMoney() : BigDecimal.ZERO;
        BigDecimal paymentRemainingAmount = paymentAmount.subtract(paymentMatchedAmount);
        
        // 确保付款记录还有剩余可匹配金额
        if (paymentRemainingAmount.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("付款记录ID {} 已经完全匹配，剩余可匹配金额为0", targetPayment.getId());
            return false;
        }
        
        // 计算实际匹配金额（取交易流水剩余金额和付款记录剩余金额的较小值）
        BigDecimal actualMatchAmount = remainingAmount.min(paymentRemainingAmount);
        
        // 创建匹配记录
        TransactionPaymentMatch match = new TransactionPaymentMatch();
        match.setTransactionId(transaction.getId());
        match.setPaymentId(targetPayment.getId());
        match.setMatchAmount(actualMatchAmount);
        match.setMatchTime(new Date());
        match.setCreateTime(new Date());
        match.setUpdateTime(new Date());
        log.info("创建交易流水与付款记录的匹配关系: 交易流水ID={}, 付款记录ID={}, 匹配金额={}", 
                 transaction.getId(), targetPayment.getId(), actualMatchAmount);
        
        int result = transactionPaymentMatchMapper.insert(match);
        if (result > 0) {
            log.info("成功创建匹配关系，匹配ID: {}", match.getId());
        } else {
            log.error("创建匹配关系失败，交易流水ID: {}, 付款记录ID: {}", transaction.getId(), targetPayment.getId());
            return false;
        }
        
        // 更新交易流水的已匹配金额，通过查询汇总的方式确保数据准确性
        BigDecimal updatedMatchedAmount = getMatchedAmountByTransactionId(transaction.getId());
        transaction.setMatchedAmount(updatedMatchedAmount);
        transactionsMapper.updateById(transaction);
        log.debug("更新交易流水ID {} 的已匹配金额为: {}", transaction.getId(), transaction.getMatchedAmount());
        
        // 检查并更新付款记录状态
        log.debug("检查并更新付款记录状态，付款记录ID: {}", targetPayment.getId());
        checkAndUpdatePaymentState(targetPayment.getId());
        log.info("完成交易流水与代办付款记录的自动匹配, 交易流水ID: {}", transaction.getId());
        
        return result > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean checkAndUpdatePaymentState(Long paymentId) {
        // 获取付款记录
        PaymentPurchase payment = paymentPurchaseMapper.selectById(paymentId);
        if (payment == null) {
            log.info("根据{}获取付款记录不存在。", paymentId);
            return false;
        }

        // 计算已匹配的总金额
        BigDecimal matchedAmount = getMatchedAmountByPaymentId(paymentId);
        BigDecimal paymentAmount = payment.getMoney() != null ? payment.getMoney() : BigDecimal.ZERO;

        // 如果已匹配金额等于付款金额，且当前状态不是已付（state != 1），则更新状态
        if (matchedAmount.compareTo(paymentAmount) >= 0 && 
            (payment.getState() == null || payment.getState() != 1)) {
            
            payment.setState(1); // 设置为实际已付
            return paymentPurchaseMapper.updateById(payment) > 0;
        }
        
        return false;
    }
}